package com.whjk.system.biz.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.whjk.core.common.utils.PinYinUtil;
import com.whjk.system.biz.mapper.WhjkZdjywhMapper;
import com.whjk.system.biz.service.*;
import com.whjk.system.data.dto.WhjkPackageRelDto;
import com.whjk.system.data.dto.WhjkPackageRelInfoDto;
import com.whjk.system.data.dto.WhjkZdjywhDto;
import com.whjk.system.data.dto.WhjkZdjywhRuleDto;
import com.whjk.system.data.entity.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 诊断建议主表 服务实现类
 * </p>
 *
 * @author hl
 * @since 2023-06-28
 */
@Service
public class WhjkZdjywhServiceImpl extends ServiceImpl<WhjkZdjywhMapper, WhjkZdjywh> implements WhjkZdjywhService {

    @Autowired
    private WhjkZdjywhInfoService whjkZdjywhInfoService;
    @Autowired
    private WhjkZdjywhInfoService zdjywhInfoService;
    @Autowired
    private WhjkZdjywhRuleService zdjywhRuleService;
    @Autowired
    private WhjkPersonService personService;

    //添加主表同时也要添加从表
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addSuggestionTable(WhjkZdjywhDto whjkZdjywhDto) {
        List<WhjkZdjywhRuleDto> zdjywhRuleList = whjkZdjywhDto.getZdjywhRuleList();
        Assert.isTrue(zdjywhRuleList.size() > 0, "逻辑规则不能为空");
        whjkZdjywhDto.setQyjm(PinYinUtil.getPinyin(whjkZdjywhDto.getZyzd()));
        whjkZdjywhDto.setWbjm(whjkZdjywhDto.getQyjm());
        this.save(whjkZdjywhDto);
        //保存建议
        List<WhjkZdjywhInfo> infoList = whjkZdjywhDto.getInfoList();
        infoList.forEach(f -> f.setZdjyId(whjkZdjywhDto.getId()));
        zdjywhInfoService.saveBatch(infoList);
        //保存条件
        List<WhjkZdjywhRule> collect = zdjywhRuleList.stream().map(f -> {
            WhjkZdjywhRule whjkZdjywhRule = new WhjkZdjywhRule();
            f.setZdjywhId(whjkZdjywhDto.getId());
            BeanUtils.copyProperties(f, whjkZdjywhRule);
            return whjkZdjywhRule;
        }).collect(Collectors.toList());
        zdjywhRuleService.saveBatch(collect);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateZdjywh(WhjkZdjywhDto whjkZdjywhDto) {
        this.updateById(whjkZdjywhDto);
        //修改建议
        zdjywhInfoService.remove(new LambdaQueryWrapper<WhjkZdjywhInfo>()
                .eq(WhjkZdjywhInfo::getZdjyId, whjkZdjywhDto.getId()));
        List<WhjkZdjywhInfo> infoList = whjkZdjywhDto.getInfoList();
        infoList.forEach(f -> f.setZdjyId(whjkZdjywhDto.getId()));
        zdjywhInfoService.saveBatch(infoList);
        //修改条件
        zdjywhRuleService.remove(new LambdaQueryWrapper<WhjkZdjywhRule>()
                .eq(WhjkZdjywhRule::getZdjywhId, whjkZdjywhDto.getId()));
        List<WhjkZdjywhRuleDto> zdjywhRuleList = whjkZdjywhDto.getZdjywhRuleList();
        List<WhjkZdjywhRule> collect = zdjywhRuleList.stream().map(f -> {
            WhjkZdjywhRule whjkZdjywhRule = new WhjkZdjywhRule();
            f.setZdjywhId(whjkZdjywhDto.getId());
            BeanUtils.copyProperties(f, whjkZdjywhRule);
            return whjkZdjywhRule;
        }).collect(Collectors.toList());
        zdjywhRuleService.saveBatch(collect);
    }

    @Override
    public WhjkZdjywhDto queryMasterSlaveTable(String id) {
        WhjkZdjywhDto whjkZdjywhDto = new WhjkZdjywhDto();
        WhjkZdjywh whjkZdjywh = this.baseMapper.selectById(id);
        BeanUtils.copyProperties(whjkZdjywh, whjkZdjywhDto);
        whjkZdjywhDto.setInfoList(whjkZdjywhInfoService.list(new LambdaQueryWrapper<WhjkZdjywhInfo>()
                .eq(WhjkZdjywhInfo::getDelFlag, 0)
                .eq(WhjkZdjywhInfo::getZdjyId, id)));
        List<WhjkZdjywhRuleDto> list = zdjywhRuleService.listByZhxm(new QueryWrapper<>()
                .eq("t1.zdjywh_id", id)
                .eq("t1.del_flag", 0));
        whjkZdjywhDto.setZdjywhRuleList(list);
        return whjkZdjywhDto;
    }

    @Override
    public Page<WhjkZdjywhDto> queryProposalForm(WhjkZdjywhDto proposalForm) {
        Page<WhjkZdjywhDto> whjkZdjywhDtoPage = this.baseMapper.queryProposalForm(new Page<>(proposalForm.getCurrent(), proposalForm.getSize()), new QueryWrapper<>()
                .eq(StringUtils.isNotBlank(proposalForm.getZhxmId()), "t1.zhxm_id", proposalForm.getZhxmId())
                .eq("t1.del_flag", 0)
                .eq("t2.del_flag", 0)
                .groupBy("t2.id", "t2.zyzd"));
        whjkZdjywhDtoPage.getRecords().forEach(f-> {
            List<WhjkZdjywhInfo> list = zdjywhInfoService.list(new LambdaQueryWrapper<WhjkZdjywhInfo>()
                    .eq(WhjkZdjywhInfo::getZdjyId, f.getId())
                    .eq(WhjkZdjywhInfo::getDelFlag, 0));
            f.setInfoList(list);
        });
        return whjkZdjywhDtoPage;
    }

    @Override
    public Page<WhjkZdjywh> getByzhxmId(WhjkZdjywhRuleDto whjkZdjywhRuleDto) {
        return this.baseMapper.getByzhxmId(new Page<>(whjkZdjywhRuleDto.getCurrent(), whjkZdjywhRuleDto.getSize()), new QueryWrapper<>()
                .eq("t1.zhxm_id", whjkZdjywhRuleDto.getZhxmId())
                .eq("t1.del_flag", 0)
                .eq("t2.del_flag", 0)
                .like(StringUtils.isNotBlank(whjkZdjywhRuleDto.getZyzd()), "t2.zyzd", whjkZdjywhRuleDto.getZyzd())
                .groupBy("t2.id"));
    }

    @Override
    public void deleteZdjywh(WhjkZdjywhDto zdjywhDto) {
        WhjkZdjywh whjkZdjywh = new WhjkZdjywh();
        BeanUtils.copyProperties(zdjywhDto, whjkZdjywh);
        this.updateById(whjkZdjywh);
    }

    @Override
    public List<WhjkZdjywhDto> getZdResult(WhjkPackageRelDto packageRelDto) {
        List<WhjkPackageRelInfoDto> infoList = packageRelDto.getPackageRelInfoList();
        WhjkPerson byId = personService.getById(packageRelDto.getPeId());
        String gender = byId.getGender();
        //根据zhxmid查询所有病例
        List<WhjkZdjywh> zdjywhList = this.baseMapper.getByzhxmId(new QueryWrapper<>()
                .eq("t1.zhxm_id", packageRelDto.getXmId())
                .eq("t1.del_flag", 0)
                .eq("t2.del_flag", 0))
                .stream().filter(f -> "2".equals(f.getGenderAppropriate()) || gender.equals(f.getGenderAppropriate()))
                .collect(Collectors.toList());
        //通过检查结果获取诊断结果
        List<WhjkZdjywhDto> zdjywhDtoList = zdjywhList.stream().filter(f -> {
            // 该病例下的规则
            List<WhjkZdjywhRule> list = zdjywhRuleService.list(new LambdaQueryWrapper<WhjkZdjywhRule>()
                    .eq(WhjkZdjywhRule::getZdjywhId, f.getId())
                    .eq(WhjkZdjywhRule::getDelFlag, 0));
            //0满足一个，1全部满足
            return f.getJudgmentCondition().equals("0")
                    ? list.stream().anyMatch(i -> checkRule(packageRelDto, infoList, i))  // anyMatch是否存在匹配
                    : list.stream().allMatch(i -> checkRule(packageRelDto, infoList, i)); // allMatch所有元素是否都匹配
        }).map(m -> {
            //诊断建议
            WhjkZdjywhDto zdjywhDto = new WhjkZdjywhDto();
            BeanUtils.copyProperties(m, zdjywhDto);
            zdjywhDto.setInfoList(zdjywhInfoService.list(new LambdaQueryWrapper<WhjkZdjywhInfo>()
                    .eq(WhjkZdjywhInfo::getZdjyId, zdjywhDto.getId())
                    .eq(WhjkZdjywhInfo::getDelFlag, 0)));
            return zdjywhDto;
        }).collect(Collectors.toList());
        //通过常见结果获取诊断结果
        List<WhjkPackageRelInfoDto> infoCjList = infoList.stream().filter(f -> StringUtils.isNotEmpty(f.getJgId())).collect(Collectors.toList());
        if (infoCjList.size() > 0){
            zdjywhDtoList.addAll(
                    infoCjList.stream().map(m -> {
                        WhjkZdjywhDto zdjywhDto = new WhjkZdjywhDto();
                        WhjkZdjywh zdjywh = this.baseMapper.getZdjywh(m.getJgId());
                        if (zdjywh != null) {
                            BeanUtils.copyProperties(zdjywh, zdjywhDto);
                            zdjywhDto.setInfoList(zdjywhInfoService.list(new LambdaQueryWrapper<WhjkZdjywhInfo>()
                                    .eq(WhjkZdjywhInfo::getZdjyId, zdjywhDto.getId())
                                    .eq(WhjkZdjywhInfo::getDelFlag, 0)));
                        } else {
                            zdjywhDto = null;
                        }
                        return zdjywhDto;
                    }).collect(Collectors.toList())
            );
        }
        return zdjywhDtoList.stream().distinct().collect(Collectors.toList());
    }

    /**
     * 用于体检结果是否符合病例
     * @param packageRelDto
     * @param infoList
     * @param rule
     * @return
     */
    private boolean checkRule(WhjkPackageRelDto packageRelDto, List<WhjkPackageRelInfoDto> infoList, WhjkZdjywhRule rule) {
        if ("-1".equals(rule.getJcxmId())) {  //根据小结
            return packageRelDto.getXmId().equals(rule.getZhxmId())
                    && judgement(packageRelDto.getSummarize(), rule.getType(), rule.getRegularValue());
        } else if ("-2".equals(rule.getJcxmId())) {  //根据检查结果
            return packageRelDto.getXmId().equals(rule.getZhxmId())
                    && judgement(packageRelDto.getAuxiliaraResult(), rule.getType(), rule.getRegularValue());
        } else {  //根据小项结果
            return infoList.stream().anyMatch(j ->
                    j.getZhxmId().equals(rule.getZhxmId())
                            && j.getJcxmId().equals(rule.getJcxmId())
                            && judgement(j.getCheckResult(), rule.getType(), rule.getRegularValue()));
        }
    }


    /**
     * 用于判断结果是否符合规则
     *
     * @param result 结果值
     * @param type   判断类型
     * @param value  判断值
     * @return
     */
    public boolean judgement(String result, String type, String value) {
        try {
            if (StringUtils.isEmpty(result) ||StringUtils.isEmpty(value) ) return false;
            double resultInt = 0;
            double valueInt = 0;
            if (!"LIKE".equals(type)) {
                resultInt = Double.parseDouble(result);
                valueInt = Double.parseDouble(value);
            }
            switch (type) {
                case "EQ":
                    return resultInt == valueInt;
                case "NE":
                    return resultInt != valueInt;
                case "GT":
                    return resultInt > valueInt;
                case "GE":
                    return resultInt >= valueInt;
                case "LT":
                    return resultInt < valueInt;
                case "LE":
                    return resultInt <= valueInt;
                case "LIKE":
                    return result.contains(value);
                default:
                    return false;
            }
        } catch (Exception e) {
            log.error("设置的规则有误,请修改!!!");
            return false;
        }
    }
}
